﻿#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif

#include "ffmpegwidget.h"
#include "ui_ffmpegwidget.h"

FFmpegWidget::FFmpegWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FFmpegWidget)
{
    ui->setupUi(this);

    initState();
    initInfoWidget();
}

FFmpegWidget::~FFmpegWidget()
{
    close();
    delete ui;
}

void FFmpegWidget::initFFmpegLib()
{
    //注册库中所有可用的文件格式和解码器
    av_register_all();

    //初始化网络流格式,使用网络流时必须先执行
    avformat_network_init();

    //初始化设备
    avdevice_register_all();

    //初始化过滤器
    avfilter_register_all();

    qDebug() << "FFmpeg Version" << FFMPEG_VERSION;
}

void FFmpegWidget::initState()
{
    image = QImage();

    thread = new FFmpegThread(this);
    connect(thread, &FFmpegThread::sendImage, this, &FFmpegWidget::updateImage);
    connect(thread, &FFmpegThread::sendPlayStart, this, &FFmpegWidget::threadPlayStart);
    connect(thread, &FFmpegThread::sendPlayError, this, &FFmpegWidget::threadPlayError);
    connect(thread, &FFmpegThread::sendPlayFinish, this, &FFmpegWidget::threadPlayFinish);
    connect(thread, &FFmpegThread::sendPlayPosition, this, &FFmpegWidget::threadPlayPosition);

    ui->showWidget->setVisible(false);
    ui->showWidget->installEventFilter(this);

    progressWait = new ProgressWait(this);
    progressWait->setVisible(false);

    bgText = "画面";
    isSelect = false;
}

void FFmpegWidget::initInfoWidget()
{
    //仅测试效果，无实际逻辑
    infoWidget = new QWidget(this);
    infoWidget->setStyleSheet("background-color:rgba(100,100,100,30)");

    QHBoxLayout *layout = new QHBoxLayout();
    infoWidget->setLayout(layout);

    btn1 = new QPushButton("OSD1");
    btn2 = new QPushButton("OSD2");
    btn1->setStyleSheet("color:red;background-color:transparent");
    btn2->setStyleSheet("color:red;background-color:transparent");
    layout->addWidget(btn1);
    layout->addWidget(btn2);

    infoWidget->setVisible(false);
}


void FFmpegWidget::setPlayUrl(const QString &url)
{
    thread->setPlayUrl(url);
    thread->setPositionEnable(true);
}

void FFmpegWidget::open()
{
    int delayMs = 30;
    if (thread->isRunning())
    {
        close();
        delayMs = 200;
    }

    QTimer::singleShot(delayMs, this, [=]()
    {
        bgText = "";
        playStatus = Play_Default;
        clear();

        progressWait->startWait();
        thread->startPlay();
        thread->start();
    });
}

void FFmpegWidget::close()
{
    ui->showWidget->setVisible(false);
    if (thread->isRunning())
    {
        thread->stopPlay();
        thread->quit();
        thread->wait(150);
    }

    bgText = "画面";
    progressWait->stopWait();
    QTimer::singleShot(50, this, &FFmpegWidget::clear);
}

void FFmpegWidget::pause()
{
    thread->pausePlay();
}

void FFmpegWidget::next()
{
    thread->nextPlay();
}

void FFmpegWidget::clear()
{
    image = QImage();
    this->update();
}

void FFmpegWidget::msSleep(int msec)
{
    QEventLoop loop;
    QTimer::singleShot(msec,&loop,SLOT(quit()));
    loop.exec();
}

int FFmpegWidget::getLength()
{
    return thread->getLength();
}

void FFmpegWidget::setPlayAudioEnable(bool enable)
{
    thread->setAudioEnable(enable);
}

void FFmpegWidget::setPlayPosition(qint64 position)
{
    if(playStatus == Play_Start)
    {
        thread->setPlayPosition(position);
    }
}

void FFmpegWidget::setSendPositionEnable(bool enable)
{
    thread->setPositionEnable(enable);
}

int FFmpegWidget::getPlayStatus()
{
    return this->playStatus;
}

void FFmpegWidget::setPlaySpeed(int level)
{
    thread->setPlaySpeed(level);
}

int FFmpegWidget::getVideoWidth()
{
    return thread->getVideoWidth();
}

int FFmpegWidget::getVideoHeight()
{
    return thread->getVideoHeight();
}

void FFmpegWidget::startCapture(const QString &path)
{
    QScreen *screen = QApplication::primaryScreen();
    QPixmap pixmap = screen->grabWindow(this->winId(), 0, 0, width(), height());

    QString picPath = path;
    if(path.isEmpty())
    {
        QString picName = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
        picPath = QString("./%1.jpg").arg(picName);
    }

    bool status = pixmap.save(picPath,"JPG",100);
    if(!status)
    {
        qDebug() << "截图失败";
    }
}

void FFmpegWidget::startSaveFile(const QString &path)
{
    QString videoPath = path;
    if(videoPath.isEmpty())
    {
        QString videoName = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
        videoPath = QString("./%1.mp4").arg(videoName);
    }

    thread->startSaveFile(videoPath);
}

void FFmpegWidget::stopSaveFile()
{
    thread->stopSaveFile();
}

void FFmpegWidget::drawNote(QPainter *painter)
{
    painter->save();

    QPen pen;
    pen.setWidth(3);
    pen.setColor(Qt::blue);
    painter->setPen(pen);

    QFont font;
    font.setPixelSize(24);
    painter->setFont(font);

    int height = this->height() / 2;
    int width = this->width() / 2;
    painter->drawText(width-25,height-20,bgText);

    painter->restore();
}

void FFmpegWidget::drawBorder(QPainter *painter)
{
    painter->save();

    QPen pen;
    pen.setWidth(3);
    pen.setColor(isSelect ? Qt::red : Qt::green);

    painter->setPen(pen);
    painter->drawRect(this->rect());

    painter->restore();
}

void FFmpegWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

    drawNote(&painter);
    drawBorder(&painter);
}

bool FFmpegWidget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->showWidget && event->type() == QEvent::Paint)
    {      
        QPainter painter(ui->showWidget);
        painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

        painter.drawImage(ui->showWidget->rect(), image);
        return true;
    }

    return QWidget::eventFilter(watched, event);
}

void FFmpegWidget::resizeEvent(QResizeEvent *)
{
    //操作控件
    infoWidget->setGeometry(10,5,this->width()-20,40);

    //等待提示
    int centerX = this->rect().center().x();
    int centerY = this->rect().center().y();
    progressWait->setGeometry(centerX-60,centerY-60,120,120);
}

void FFmpegWidget::enterEvent(QEvent *)
{
    infoWidget->setVisible(true);
    isSelect = true;
    update();
}

void FFmpegWidget::leaveEvent(QEvent *)
{
    isSelect = false;
    update();
    infoWidget->setVisible(false);
}

void FFmpegWidget::updateImage(const QImage &image)
{
    if(image.isNull())
    {
        return;
    }

    this->image = image;
    this->update();
}


void FFmpegWidget::threadPlayStart()
{
    ui->showWidget->setVisible(true);
    progressWait->stopWait();
    playStatus = Play_Start;

    emit sendPlayStart();
}

void FFmpegWidget::threadPlayError()
{
    progressWait->stopWait();
    playStatus = Play_Error;
    bgText = "播放失败";
    update();
    qDebug() << "播放出错";
}

void FFmpegWidget::threadPlayFinish()
{
    playStatus = Play_Finish;

    ui->showWidget->setVisible(false);
    emit sendPlayFinish();
}

void FFmpegWidget::threadPlayPosition(int sec)
{
    emit sendPlayPosition(sec);
}
